package com.zone.gateway.core.authorization;

import io.jsonwebtoken.Claims;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author: zongzi
 * @description: 网关授权Realm，处理JWT token认证
 * @date: 2025/4/22
 */
public class GatewayAuthorizingRealm extends AuthorizingRealm {

    private static final Logger logger = LoggerFactory.getLogger(GatewayAuthorizingRealm.class);

    /**
     * 判断是否支持该Token类型
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof GatewayAuthenticationToken;
    }

    // 用于授权的方法
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    // 用于身份验证的方法
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        if (!(authenticationToken instanceof GatewayAuthenticationToken)) {
            logger.error("不支持的Token类型: {}", authenticationToken.getClass().getName());
            throw new AuthenticationException("不支持的Token类型");
        }

        GatewayAuthenticationToken gatewayToken = (GatewayAuthenticationToken) authenticationToken;
        try {
            // 验证JWT token
            Claims claims = JwtUtils.decode(gatewayToken.getJwt());
            if (!claims.getSubject().equals(gatewayToken.getuId())) {
                logger.error("token uid = {}, subject = {}", gatewayToken.getuId(), claims.getSubject());
                throw new AuthenticationException("签发人校验未通过");
            }
            logger.info("JWT token验证成功, channelId: {}", gatewayToken.getuId());
        } catch (Exception e) {
            logger.error("JWT token验证失败: {}", e.getMessage());
            throw new AuthenticationException("无效令牌: " + e.getMessage());
        }

        return new SimpleAuthenticationInfo(
                gatewayToken.getuId(),  // 使用channelId作为principal
                gatewayToken.getJwt(),         // 使用JWT作为credentials
                this.getName()                 // realm名称
        );
    }
}
